package com.example.opengl.render.triangle

import android.opengl.GLES20
import android.opengl.GLES30
import androidx.core.app.NavUtils
import com.bumptech.glide.disklrucache.DiskLruCache.Value
import com.example.opengl.base.BufferHelper
import com.example.opengl.base.ShaderHelper
import com.example.opengl.render.base.Drawer
import com.example.opengl.render.base.IDrawer
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer


class TriangleDrawer(val type: Drawer) : IDrawer {
    /**
     * 顶点坐标 - 点
     */
    private val mVertexCoorsPoint = floatArrayOf(
        0.6f, 0.6f,
        -0.6f, 0.6f,
        0f, 0.98f
    )

    /**
     * 纹理坐标 - 点
     */
    private val mTextureCoorsPoint = floatArrayOf(
        0.6f, 0.6f,
        -0.6f, 0.6f,
        0f, 1f
    )


    /**
     * 顶点坐标 - 线
     */
    private val mVertexCoorsLine = floatArrayOf(
        0f, 0.5f,
        -0.6f, -0.1f,
        0.6f, -0.1f
    )

    /**
     * 纹理坐标 - 线
     */
    private val mTextureCoorsLine = floatArrayOf(
        0f, 1f,
        1f, 1f,
        0.5f, 0f
    )

    /**
     * 顶点坐标 - 面
     */
    private val mVertexCoorsTriangle = floatArrayOf(
        0f, -0.12f,
        -0.7f, -0.7f,
        0.7f, -0.7f
    )

    /**
     * 纹理坐标 - 面
     */
    private val mTextureCoorsTriangle = floatArrayOf(
        0.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 0.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f, 1.0f
    )


    private var mTexures: FloatArray? = null
    private var mVertexs: FloatArray? = null


    /**
     * 纹理id
     */
    private var mTextureId: Int = -1

    /**
     * OpenGl程序id
     */
    private var mProgram: Int = -1

    /**
     * 顶点坐标接收者
     */
    private var mVertexPosHandler = -1

    /**
     * 纹理坐标接收者
     */
    private var mTexturePosHandler = -1

    private var mScreenWidth = 0
    private var mScreenHeight = 0

    private var mVideoWidth = 0
    private var mVideoHeight = 0

    private lateinit var mVertexBuffer: FloatBuffer
    private lateinit var mTextureBuffer: FloatBuffer

    init {
        //初始化顶点坐标
        initPos()
    }

    private fun initPos() {

        when (type) {
            Drawer.point -> {
                mVertexs = mVertexCoorsPoint
                mTexures = mTextureCoorsPoint
            }

            Drawer.line -> {
                mVertexs = mVertexCoorsLine
                mTexures = mTextureCoorsLine
            }

            else -> {
                mVertexs = mVertexCoorsTriangle
                mTexures = mTextureCoorsTriangle
            }
        }
        mVertexBuffer = BufferHelper.getFloatBuffer(mVertexs!!)
        mTextureBuffer = BufferHelper.getFloatBuffer(mTexures!!)

        /* //分配系统内存给顶点坐标
         val bb = ByteBuffer.allocateDirect(mVertexCoors.size * 4)
         bb.order(ByteOrder.nativeOrder())
         //将坐标数据转换成bytebuffer
         mVertexBuffer = bb.asFloatBuffer()
         mVertexBuffer.put(mVertexCoors)
         mVertexBuffer.position(0)

         //分配系统内存给纹理坐标
         val cc = ByteBuffer.allocateDirect(mTextureCoors.size * 4)
         cc.order(ByteOrder.nativeOrder())
         mTextureBuffer = cc.asFloatBuffer()
         mTextureBuffer.put(mTextureCoors)
         mTextureBuffer.position(0)*/
    }


    override fun draw() {
        if (mTextureId != -1) {
            initGLProgram()
            doDraw()
        }
    }

    private fun initGLProgram() {
        if (mProgram == -1) {
            //加载顶点坐标程序
            val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, getVertexShader())
            val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, getFragmentShader())
            //创建OpenGL程序
            mProgram = GLES20.glCreateProgram()
            //将顶点着色器加入OpenGL程序中
            GLES20.glAttachShader(mProgram, vertexShader)
            //将纹理着色器加入OpenGL程序中
            GLES20.glAttachShader(mProgram, fragmentShader)
            //链接着色器程序
            GLES20.glLinkProgram(mProgram)
            // 返回 attribute 属性变量的 location（索引值）
            mVertexPosHandler = GLES20.glGetAttribLocation(mProgram, "aPosition")
            mTexturePosHandler = GLES20.glGetAttribLocation(mProgram, "aCoordinate")
        }
        //使用OpenGL程序
        GLES20.glUseProgram(mProgram)
    }


    private fun loadShader(shaderType: Int, shaderCode: String): Int {
        //根据shaderType创建着色器
        val shader = GLES20.glCreateShader(shaderType)
        //加载本地资源到着色器中
        GLES20.glShaderSource(shader, shaderCode)
        //编译着色器资源
        GLES20.glCompileShader(shader)
        return shader
    }

    private fun doDraw() {
        //GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
        //启用顶点坐标的引用
        GLES20.glEnableVertexAttribArray(mVertexPosHandler)
        GLES20.glEnableVertexAttribArray(mTexturePosHandler)
        //设置着色器参数
        GLES20.glVertexAttribPointer(mVertexPosHandler, 2, GLES20.GL_FLOAT, false, 0, mVertexBuffer)
        GLES20.glVertexAttribPointer(mTexturePosHandler, 2, GLES20.GL_FLOAT, false, 0, mTextureBuffer)
        //开始绘制
        /**
         * 绘制有两种方式:glDrawArrays和glDrawElements,
         * 区别：
         *   1.glDrawArrays 直接使用定义好的顶点顺序进行绘制
         *   2.glDrawElements 定义另外的索引数组，来确认顶点的组合绘制顺序
         *
         */
        //
        when(type){
            Drawer.point ->{
                GLES20.glDrawArrays(GLES20.GL_POINTS,0,3) //点
            }
            Drawer.line ->{
                GLES20.glDrawArrays(GLES20.GL_LINE_LOOP, 0, 3) //线
            }
            else->{
                GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP,0,3) //填充模式
            }
        }

        GLES20.glLineWidth(10f)

    }


    override fun setTextureID(id: Int) {
        mTextureId = id
    }

    override fun release() {
        //释放顶点坐标和纹理坐标引用
        GLES20.glDisableVertexAttribArray(mVertexPosHandler)
        GLES20.glDisableVertexAttribArray(mTexturePosHandler)
        //将绑定的texture置为空
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0)
        GLES20.glDeleteTextures(1, intArrayOf(mTextureId), 0)
        GLES20.glDeleteProgram(mProgram)

    }

    override fun setWorldSize(worldW: Int, worldH: Int) {
        mScreenWidth = worldH
        mScreenHeight = worldW
    }

    override fun setVideoSize(videoW: Int, videoH: Int) {
        mVideoWidth = videoW
        mVideoHeight = videoH
    }

    private fun getVertexShader(): String {
        return "attribute vec4 aPosition;" +
                "void main(){" +
                "  gl_Position = aPosition;" +
                "}"
    }

    private fun getFragmentShader(): String {
        return "precision mediump float;" +
                "void main(){" +
                "  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);" +
                "}"
    }
}